home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / demos / video / trails.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  19KB  |  703 lines

  1. /*
  2.  * Copyright (C) 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. /*
  18.  * File:     trails.c
  19.  *
  20.  * Usage:    trails.c     [-f] [-d] [-n devicenum] [-t title] 
  21.  *                [-v videosource] [-I] [-h]
  22.  *                   
  23.  *
  24.  * Description: Modification of simpleblend to use frame buffer connected to
  25.  *        blender output, and then fed back into blender background.
  26.  *        Simpleblend is an example of blending video with graphics. It
  27.  *         does not do any special setup, but it does show the output 
  28.  *        in a graphics window and on video out. This program only
  29.  *        runs on video hardware that has a video output port.
  30.  *        This program will only run on the Galileo or IndyVideo board
  31.  *
  32.  * Functions:    SGI Video Library functions used (see other modules)
  33.  *
  34.  *        vlOpenVideo()
  35.  *        vlGetDeviceList()
  36.  *        vlGetNode()
  37.  *        vlCreatePath()
  38.  *        vlAddNode()
  39.  *        vlGetDevice()
  40.  *        vlSetupPaths()
  41.  *        vlSelectEvents()
  42.  *        vlRegisterHandler()
  43.  *        vlAddCallback()
  44.  *        vlSetControl()
  45.  *        vlGetControl()
  46.  *        vlMainLoop()
  47.  *        vlBeginTransfer()
  48.  *        vlEndTransfer()
  49.  *        vlDestroyPath()
  50.  *        vlCloseVideo()
  51.  *        vlGetErrno()
  52.  *        vlPerror()
  53.  *        vlStrError()
  54.  *
  55.  */
  56.  
  57. #include <sys/types.h>
  58. #include <stdio.h>
  59. #include <stdlib.h>
  60. #include <unistd.h>
  61. #include <string.h>
  62.  
  63. #include <X11/X.h>
  64. #include <X11/Xlib.h>
  65. #include <X11/Xutil.h>
  66. #include <Xm/MwmUtil.h>
  67.  
  68. #include <vl/vl.h>
  69. #include <vl/dev_ev1.h>
  70.  
  71. #include <gl/gl.h>
  72. #include <gl/device.h>
  73.  
  74. /*
  75.  *  Function prototypes
  76.  */
  77.  
  78. void    VideoTracking(Window, int,int);
  79. void    processXEvent(uint, void *);
  80. void    processVLEvent(VLServer, VLEvent *, void *);
  81. void    docleanup(void);
  82. void    usage(void);
  83.  
  84. VLServer    vlSvr = NULL;
  85. VLPath        vlPath = -1;
  86. VLDevList    devlist;
  87. VLNode        src_vid;
  88. VLNode        src_scr;
  89. VLNode        drn_scr;
  90. VLNode        drn_vid;
  91. VLNode        drn_mem;        /* memory drain (frame buffer) */
  92. VLNode        mydev_node;     /* device node to allow setting of sync mode */
  93. VLNode        blend_node;    /* 'cause blending controls are here */
  94.  
  95. VLBuffer buffer;
  96. int imageCount = 1;
  97.  
  98. Display        *dpy;
  99. Window        drnwin;
  100. int        vin = VL_ANY;
  101. char        *_progname;
  102. char        *deviceName;
  103. int        devicenum = -1;
  104. int        ev1num = -1;
  105. int        debug = 0;
  106.  
  107. Atom WM_DELETE_WINDOW;
  108. Atom WM_PROTOCOLS;
  109.  
  110. int lastw = 0, lasth = 0;
  111.  
  112. #define Debug    if (debug) printf
  113. #define fDebug    if (debug) fprintf
  114.  
  115. #define ESC_KEY '\006'
  116.  
  117. #define USAGE \
  118. "%s: [-f] [-n <devicenum>] [-t] [-d] [-I] [-v <videonode> ] [-h]\n\
  119. \t-f\tdisable forking\n\
  120. \t-n n\tdevice number to use\n\
  121. \t-t\tset window title\n\
  122. \t-d\tdebug mode\n\
  123. \t-I\tprint node and path IDs for command line interface users\n\
  124. \t-v n\tvideo source node number n\n\
  125. \t-h\tthis help message\n"
  126.  
  127. void 
  128. usage()
  129. {
  130.     fprintf(stderr, USAGE, _progname);
  131. }
  132.  
  133. /* Constrain the window's aspect ratio */
  134. void
  135. constrainWindowResize(Display *dpy, Window win, int max_w, int max_h)
  136. {
  137.     XSizeHints xsh;
  138.  
  139.     xsh.min_aspect.x = xsh.max_aspect.x = 80;
  140.     xsh.min_aspect.y = xsh.max_aspect.y = 60;
  141.     xsh.min_width  = max_w;
  142.     xsh.min_height = max_h;
  143.     xsh.max_width  = max_w;
  144.     xsh.max_height = max_h;
  145.     xsh.flags = PAspect|PMinSize|PMaxSize;
  146.  
  147.     XSetWMNormalHints(dpy, win, &xsh);
  148.     XResizeWindow(dpy, win, max_w, max_h);
  149. }
  150.  
  151. simplev2v()
  152. {
  153.     VLServer svr;
  154.     VLPath VIDPath;
  155.     VLNode src, drn;
  156.     int c;
  157.     int devicenum = -1;
  158.     char *_progName;
  159.  
  160.     /* Connect to the daemon */
  161.     if (!(svr = vlOpenVideo(""))) 
  162.     {
  163.     printf("%s: can't open video: %s\n", _progName, vlStrError(vlGetErrno()));
  164.     docleanup();
  165.     }
  166.  
  167.     /* Set up a source node on the first available video device */
  168.     src = vlGetNode(svr, VL_SRC, VL_VIDEO, VL_ANY);
  169.     
  170.     /* Set up a video drain node on the first device that has one */
  171.     drn = vlGetNode(svr, VL_DRN, VL_VIDEO, VL_ANY); 
  172.     
  173.     /* Create a path using the selected device(s) */
  174.     if (devicenum == -1)
  175.     VIDPath = vlCreatePath(svr, VL_ANY, src, drn);
  176.     else
  177.     VIDPath = vlCreatePath(svr, devicenum, src, drn);
  178.  
  179.     /* Set up the hardware for and define the usage of the path */
  180.     if (vlSetupPaths(svr, (VLPathList)&VIDPath, 1, VL_SHARE, VL_SHARE)<0)
  181.     {
  182.     printf("%s: can't setup path: %s\n", _progName, vlStrError(vlGetErrno()));
  183.     docleanup();
  184.     }
  185.  
  186.     /* Begin the data transfer */
  187.     vlBeginTransfer(svr, VIDPath, 0, NULL);
  188.  
  189.     /* End the data transfer */
  190.     vlEndTransfer(svr, VIDPath);
  191.     
  192.     /* Clean up and exit */
  193.     vlDestroyPath(svr, VIDPath);
  194.     vlCloseVideo(svr);
  195. }
  196.  
  197. main(int argc, char **argv)
  198. {
  199.     char *winname = NULL;
  200.     int opterr = 0;
  201.     int c,i;
  202.     int dev;
  203.     int ret;
  204.     int nofork = 0;
  205.     int x, y;
  206.     int print_ids = 0;
  207.     Atom WM_PROT_SET[2];
  208.     Atom _SGI_VIDEO;
  209.     VLControlValue val;
  210.     int myret;
  211.     VLTransferDescriptor xferDesc;
  212.     
  213.     _progname = argv[0];
  214.  
  215.     /*
  216.      * Parse command line options
  217.      * -f   disable forking
  218.      * -n n device number n
  219.      * -d   set debugging
  220.      * -t   set title
  221.      * -v n use video input n
  222.      * -I   print node and path IDs
  223.      * -h   display help message
  224.      */
  225.     while ((c = getopt(argc, argv, "t:dv:In:fh")) != EOF) 
  226.     {
  227.     switch(c) 
  228.     {
  229.         case 'f':
  230.         nofork = 1;
  231.         break;
  232.         
  233.         case 'n':
  234.         devicenum = atoi(optarg);
  235.         break;
  236.         
  237.         case 'd':
  238.         debug++;
  239.         break;
  240.         
  241.         case 't':
  242.         winname = optarg;
  243.         break;
  244.         
  245.         case 'I':
  246.         print_ids = 1;
  247.         break;
  248.         
  249.         case 'v':
  250.         vin = atoi(optarg);
  251.         Debug("video input = %d\n", vin);
  252.         break;
  253.         
  254.         case 'h':
  255.         usage();
  256.         exit(0);
  257.         break;
  258.     }
  259.     }
  260.  
  261.     if (opterr) 
  262.     {
  263.         usage();
  264.     exit(1);
  265.     }
  266.  
  267.     /* Run in background if no-forking option not set */
  268.     if (!nofork) 
  269.     {
  270.     ret = fork();
  271.     switch (ret) 
  272.     {
  273.         case 0:
  274.         break;
  275.         
  276.         case -1:
  277.         fprintf(stderr, "%s: can't fork\n");
  278.         exit(1);
  279.         break;
  280.         
  281.         default:
  282.         exit(0);
  283.         break;
  284.     }
  285.     }
  286.  
  287.     /* Connect to the daemon */
  288.     if (!(vlSvr = vlOpenVideo(""))) 
  289.     {
  290.     printf("%s: opening video: %s\n",_progname,vlStrError(vlGetErrno()));
  291.     exit(1);
  292.     }
  293.  
  294.     /* Get the list of devices the daemon supports */
  295.     if (vlGetDeviceList(vlSvr, &devlist) < 0) 
  296.     {
  297.     printf("%s: getting device list: %s\n",_progname,vlStrError(vlGetErrno()));
  298.     exit(1);
  299.     }
  300.  
  301.  
  302.     /* Make sure that the device the user requested (if any) is in the list */
  303.     if ((devicenum >= (int)devlist.numDevices) || (devicenum < -1))
  304.     {
  305.     if (devlist.numDevices == 1)
  306.         fprintf(stderr,"%s: The device number must be 0\n",_progname);
  307.     else
  308.         fprintf(stderr,"%s: The device number must be between 0 and %d\n",
  309.             _progname, devlist.numDevices-1);
  310.     exit(1);
  311.     }
  312.     /* find ev1 */
  313.     for (i=0; i<devlist.numDevices; i++) 
  314.         if (strcmp(devlist.devices[i].name,"ev1") == 0)
  315.         ev1num = i;
  316.     if ( (ev1num == -1) /* no ev1 found ... OR ...*/
  317.     || ((devicenum != -1) && (devicenum != ev1num))) /* non ev1 specified*/
  318.     {
  319.       printf("This program requires 'ev1' hardware.\a\n");
  320.       if (ev1num != -1) 
  321.     printf("Use device number '%d', or use the default mode\n",ev1num);
  322.       exit(1);
  323.     }else
  324.     {
  325.       printf("Setting device number to %d\n", ev1num);
  326.       devicenum = ev1num; /* allow default to work */
  327.     }
  328.  
  329.  
  330.     /*
  331.      * Establish a path between the screen source and video
  332.      * drain. Then add a video source node and a screen drain
  333.      * node.
  334.      */
  335.  
  336.     /* Setup drain nodes on the screen and video */
  337.     drn_scr = vlGetNode(vlSvr, VL_DRN, VL_SCREEN, VL_ANY);
  338. Debug("drn_scr = %d\n", drn_scr);
  339.     drn_vid = vlGetNode(vlSvr, VL_DRN, VL_VIDEO, VL_ANY);
  340. Debug("drn_vid = %d\n", drn_vid);
  341.     /* Setup source nodes on the screen and video */
  342.     src_scr = vlGetNode(vlSvr, VL_SRC, VL_SCREEN, VL_ANY);
  343. Debug("src_scr = %d\n", src_scr);
  344.     src_vid = vlGetNode(vlSvr, VL_SRC, VL_VIDEO, vin);
  345. Debug("src_vid = %d\n", src_vid);
  346.  
  347.     /* Set up a drain node in memory (frame buffer) */
  348.     drn_mem = vlGetNode(vlSvr, VL_DRN, VL_MEM, VL_ANY);
  349. Debug("drn_mem = %d\n", drn_mem);
  350.  
  351.     mydev_node = vlGetNode(vlSvr, VL_DEVICE, 0,0);
  352. Debug("mydev_node = %d\n", mydev_node);
  353.     blend_node = vlGetNode(vlSvr, VL_INTERNAL, VL_BLENDER, VL_ANY);
  354. Debug("blend_node = %d\n", blend_node);
  355.  
  356.     vlPath = -1;
  357.     /* If no device was specified... */
  358.     if (devicenum == -1)
  359.     {
  360.     /* Try to create the screen to video path */
  361.     vlPath = vlCreatePath(vlSvr, devicenum, src_scr, drn_vid);
  362. Debug("vlPath = %d\n", vlPath);
  363.     /* Add the video source and screen drain nodes */
  364.     ret = vlAddNode(vlSvr, vlPath, src_vid);
  365. Debug("vlAddNode(src_vid) returns %d\n", ret);
  366.     if (!ret)
  367.         ret = vlAddNode(vlSvr, vlPath, drn_scr);
  368. Debug("vlAddNode(drn_scr) returns %d\n", ret);
  369.     if (ret)
  370.     { /* Device doesn't support this path, these nodes */
  371.         vlDestroyPath(vlSvr, vlPath);
  372.         vlPath = -1;
  373.     } 
  374.     else 
  375.     { /* Path OK, get device info */
  376.         devicenum = vlGetDevice(vlSvr, vlPath);
  377. Debug("devicenum = %d\n", devicenum);
  378.         deviceName = devlist.devices[devicenum].name;
  379. Debug("deviceName = %s\n", deviceName);
  380.     }
  381.     }
  382.     else /* User specified a device */
  383.     {    /* Get the device info */
  384.     deviceName = devlist.devices[devicenum].name;
  385.         /* Try to create the screen to video path */
  386.     vlPath = vlCreatePath(vlSvr, devicenum, src_scr, drn_vid);
  387.     /* Add the video source and screen drain nodes */
  388.     ret = vlAddNode(vlSvr, vlPath, src_vid);
  389.     if (!ret)
  390.         ret = vlAddNode(vlSvr, vlPath, drn_scr);
  391.     if (ret)
  392.     {  /* Device doesn't support this path, these nodes */
  393.         vlDestroyPath(vlSvr, vlPath);
  394.         vlPath = -1;
  395.     }
  396.     }
  397.     if (vlAddNode(vlSvr, vlPath, drn_mem))
  398.     {
  399.     vlPerror("Add memory drain  Node");
  400.     vlDestroyPath(vlSvr, vlPath);
  401.     vlPath = -1;
  402.     }
  403. Debug("vlAddNode(drn_mem)\n");
  404.  
  405.     if (vlAddNode(vlSvr, vlPath, mydev_node))
  406.     {
  407.     vlPerror("Add Device Node");
  408.     vlDestroyPath(vlSvr, vlPath);
  409.     vlPath = -1;
  410.     }
  411. Debug("vlAddNode(mydev_node)\n");
  412.  
  413.     if (vlAddNode(vlSvr, vlPath, blend_node))
  414.     {
  415.     vlPerror("Add blend Node");
  416.     vlDestroyPath(vlSvr, vlPath);
  417.     vlPath = -1;
  418.     }
  419. Debug("vlAddNode(blend_node)\n");
  420.     if (vlPath == -1)
  421.     { /* Couldn't create the path, quit */
  422.     vlPerror("Path Setup");
  423.     docleanup();
  424.     }
  425.  
  426.      /* Print the node and path IDs for cmd line users */
  427.     if (print_ids)
  428.     {
  429.     printf("SIMPLEBLEND NODE IDs:\n");
  430.     printf("screen source = %d\n", src_scr);
  431.     printf("video source = %d\n", src_vid);
  432.     printf("screen drain = %d\n", drn_scr);
  433.     printf("video drain = %d\n", drn_vid);
  434.     printf("blend = %d\n", blend_node);
  435.     printf("PATH ID = %d\n", vlPath);
  436.     }
  437.         
  438.     /* Set up the hardware for and define the usage of the path */
  439.     if (vlSetupPaths(vlSvr, (VLPathList)&vlPath, 1, VL_SHARE, VL_SHARE) < 0)
  440.     {
  441.        vlPerror("Error in device paths setup");
  442.        printf("This program requires the device Sync to be in slave mode.\n");
  443.        printf("Use the videopanel to set the device Sync to be slave.\n");
  444.        exit(1);
  445.     }
  446. Debug("vlSetupPaths()\n");
  447.  
  448.     printf("\nFor best results, use the blending controls provided\n");
  449.     printf("by the program /usr/people/4Dgifts/examples/video/vl/keyctls.\n");
  450.     printf("Interesting results can also be obtained by changing values\n");
  451.     printf("in the Pro/Video Input and Pro/Video Output control panels of \n");
  452.     printf("the videopanel.\n\n");
  453.     printf("Type 'q' inside the video window to quit\n\n");
  454.     /* Get the current size of the drain window */
  455.     vlGetControl(vlSvr, vlPath, drn_scr, VL_SIZE, &val);
  456.     lastw = val.xyVal.x;
  457.     lasth = val.xyVal.y;
  458.     /* Attempt to set the source to the same size */
  459.     vlSetControl(vlSvr, vlPath, src_scr, VL_SIZE, &val);
  460.     /* Make sure there's enough room for a source window of the same size */ 
  461.     vlGetControl(vlSvr, vlPath, src_scr, VL_SIZE, &val);
  462.  
  463.     if (lastw != val.xyVal.x || lasth != val.xyVal.y)
  464.     {
  465.     printf("%s: unable to make two full size windows\n", _progname);
  466.     docleanup();
  467.     }
  468.  
  469.     /* Set the keyer mode, keyer source and blend controls */
  470.     val.intVal = VL_EV1_KEYERMODE_LUMA;
  471.     vlSetControl(vlSvr, vlPath, blend_node, VL_EV1_KEYER_MODE, &val);
  472.     val.intVal = src_scr;
  473.     vlSetControl(vlSvr, vlPath, blend_node, VL_EV1_KEYER_SOURCE, &val);
  474. /*    val.intVal = src_scr;   */
  475.     val.intVal = src_vid;
  476.     vlSetControl(vlSvr, vlPath, blend_node, VL_BLEND_A, &val);
  477.  
  478. /*    val.intVal = src_vid;  */
  479.     val.intVal = drn_mem;
  480.     vlSetControl(vlSvr, vlPath, blend_node, VL_BLEND_B, &val);
  481.  
  482.     val.intVal = 7; 
  483.     vlSetControl(vlSvr,vlPath, blend_node, VL_EV1_KEYER_DETAIL, &val);
  484.     val.intVal = 255; 
  485.     vlSetControl(vlSvr,vlPath, blend_node, VL_EV1_KEYER_FG_OPACITY, &val);
  486.     val.intVal = 10; 
  487.     vlSetControl(vlSvr,vlPath, blend_node, VL_EV1_KEYER_VALUE_LUMA, &val);
  488.     val.intVal = 10; 
  489.     vlSetControl(vlSvr,vlPath, blend_node, VL_EV1_KEYER_RANGE_LUMA, &val);
  490.  
  491.     /* Display the drain window */
  492.     if (!(dpy = XOpenDisplay(""))) 
  493.     {
  494.     printf("%s: can't open display\n", _progname);
  495.     docleanup();
  496.     }
  497.  
  498.     drnwin = XCreateWindow(dpy, RootWindow(dpy, 0), 0, lasth, lastw, lasth, 0,
  499.                 CopyFromParent, CopyFromParent, CopyFromParent,
  500.                 (ulong) 0, NULL);
  501.  
  502.  
  503.     _SGI_VIDEO = XInternAtom(dpy, "_SGI_VIDEO", False);
  504.     WM_DELETE_WINDOW = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
  505.     WM_PROTOCOLS = XInternAtom(dpy, "WM_PROTOCOLS", False);
  506.     WM_PROT_SET[0] = WM_DELETE_WINDOW;
  507.     WM_PROT_SET[1] = _SGI_VIDEO;
  508.     XSetWMProtocols(dpy,drnwin, WM_PROT_SET, 2);
  509.  
  510.     XStoreName(dpy, drnwin, "Video Trails");
  511.     
  512.     /* Adjust the drain window's aspect ratio */
  513.     constrainWindowResize(dpy, drnwin, lastw, lasth);
  514.  
  515.     /* Set the video to appear in window drnwin */
  516.      val.intVal = drnwin;
  517.     vlSetControl(vlSvr, vlPath, drn_scr, VL_WINDOW, &val);
  518.  
  519.     /* Make sure there's room for both the source and drain window */
  520.     vlGetControl(vlSvr, vlPath, drn_scr, VL_SIZE, &val);
  521.     if (val.xyVal.x != lastw || val.xyVal.y != lasth)
  522.     {
  523.     printf("%s: Unable to setup two full size windows\n",_progname);
  524.     docleanup();
  525.     }
  526.     vlGetControl(vlSvr, vlPath, src_scr, VL_SIZE, &val);
  527.     if (val.xyVal.x != lastw || val.xyVal.y != lasth)
  528.     {
  529.     printf("%s: Unable to setup two full size windows\n",_progname);
  530.     docleanup();
  531.     }
  532.  
  533.     /* Get the location of the screen drain */
  534.     vlGetControl(vlSvr, vlPath, drn_scr, VL_ORIGIN, &val);
  535.     /* Move its window to that location */
  536.     XMoveWindow(dpy, drnwin, val.xyVal.x, val.xyVal.y);
  537.  
  538.     XMapWindow(dpy, drnwin);
  539.     XSelectInput(dpy, drnwin, KeyPressMask|VisibilityChangeMask
  540.                 |ExposureMask|StructureNotifyMask);
  541.     XSync(dpy, 0);
  542.  
  543.     /* Specify a file descriptor and pending check function for VL events */              
  544.     vlRegisterHandler(vlSvr, ConnectionNumber(dpy), processXEvent,
  545.               (VLPendingFunc)XPending, dpy);
  546.               
  547.     /* Set up event handler routine as callback for all events */
  548.     vlAddCallback(vlSvr, vlPath, VLAllEventsMask, processVLEvent, NULL);
  549.  
  550.     /* Set the VL event mask so we only get control changed events */
  551.     vlSelectEvents(vlSvr, vlPath, VLControlChangedMask);
  552.  
  553. /* ### */
  554.     /* Create and register a buffer of imageCount frames... */
  555.     buffer = vlCreateBuffer(vlSvr, vlPath, drn_mem, imageCount);
  556.     if (buffer == NULL)
  557.     {
  558.     vlPerror("trails");
  559.     docleanup();
  560.     }
  561.     if (vlRegisterBuffer(vlSvr, vlPath, drn_mem, buffer))
  562.     {
  563.     vlPerror("trails");
  564.     docleanup();
  565.     }
  566.     
  567.     /*
  568.      * Fill the transfer descriptor for a discrete transfer of imageCount
  569.      * frames. If the external trigger option is set, we use VLDeviceEvent
  570.      * for a trigger, otherwise trigger immediately. Note that this may not
  571.      * work well on all devices, as VLDeviceEvent it not well-defined.
  572.      */
  573.     xferDesc.mode = VL_TRANSFER_MODE_DISCRETE;
  574.     xferDesc.count = imageCount;
  575.     xferDesc.delay = 0;
  576.     xferDesc.trigger = VLTriggerImmediate;
  577.  
  578.     /* Start the data transfer immediately (i.e. don't wait for trigger) */
  579.     myret = vlBeginTransfer(vlSvr, vlPath, 1, &xferDesc);
  580. Debug("vlBeginTransfer() = %d\n", myret);
  581.  
  582.     /* Handle event dispatching */
  583.     vlMainLoop();
  584. }
  585.  
  586. /*
  587.  * VideoTracking - if the user changes the size of the window, 
  588.  * update the video to reflect the new size and position.
  589.  */
  590. void
  591. VideoTracking(Window win, int x, int y)
  592. {
  593.     Window dummyWin;
  594.     VLControlValue val;
  595.  
  596.     /* Get X's idea of origin */
  597.     XTranslateCoordinates(dpy, win, RootWindow(dpy, DefaultScreen(dpy)),
  598.                           0, 0,
  599.                           &x, &y,
  600.                           &dummyWin);
  601.  
  602.     /* Try to make vl match X */
  603.     val.xyVal.x = x;
  604.     val.xyVal.y = y;
  605.     if (win == drnwin)
  606.     vlSetControl(vlSvr, vlPath, drn_scr, VL_ORIGIN, &val);
  607.     else
  608.     vlSetControl(vlSvr, vlPath, src_scr, VL_ORIGIN, &val);
  609. }
  610.  
  611. /* 
  612.  * VLEvent processing for video to screen.
  613.  * We only deal with control changed events.
  614.  */
  615. void
  616. processVLEvent(VLServer vlSvr, VLEvent *ev, void *dummy)
  617. {
  618.     VLControlChangedEvent *cev = (VLControlChangedEvent *) ev;
  619.     VLControlValue val;
  620.  
  621.     Debug("VL event.type = %d\n", ev->reason);
  622.     switch (ev->reason)
  623.     {   /* Ignore all but a change in the drain's location */
  624.     case VLControlChanged:
  625.         if ((cev->type == VL_ORIGIN)&&(cev->node == drn_scr))
  626.         {
  627.             /* Drain moved, move window accordingly */
  628.         vlGetControl(vlSvr, vlPath, drn_scr, VL_ORIGIN, &val);
  629.         XMoveWindow(dpy, drnwin, val.xyVal.x, val.xyVal.y);
  630.         }
  631.     break;
  632.     }
  633. }
  634.  
  635. /* XEvent processing for video to screen */
  636. void
  637. processXEvent(uint fd, void *source)
  638. {
  639.     int i;
  640.  
  641.     if (source == (caddr_t)dpy) 
  642.     {
  643.     XEvent ev;
  644.     
  645.     XNextEvent(dpy, &ev);
  646.     switch (ev.type) 
  647.     {
  648.         case ClientMessage:
  649.         if (ev.xclient.message_type == WM_PROTOCOLS)
  650.             if (ev.xclient.data.l[0] == WM_DELETE_WINDOW)
  651.             docleanup();
  652.         break;
  653.         
  654.         case Expose:        /* These really don't effect us */
  655.         case GraphicsExpose:
  656.         case VisibilityNotify:
  657.         break;
  658.         
  659.         case ConfigureNotify:       /* Window moved or changed size */
  660.         VideoTracking(ev.xany.window, ev.xconfigure.x,ev.xconfigure.y);
  661.         break;
  662.         
  663.         case KeyPress: 
  664.         {
  665.         XKeyEvent *kev = (XKeyEvent *)&ev;
  666.         KeySym keysym;
  667.         char buf[4];
  668.                 
  669.         XLookupString(kev, buf, 1, &keysym, 0);
  670.         switch (buf[0]) 
  671.         {  
  672.             case '+':
  673.             /* Quit */
  674.             case 'q':
  675.             case 'Q':
  676.             case ESC_KEY:
  677.             docleanup();
  678.             break;
  679.             
  680.             default:
  681.             break;
  682.         }
  683.         }
  684.     }
  685.     }
  686. }
  687.  
  688. /* Dispose of the vl structures */
  689. void
  690. docleanup(void)
  691. {   /* End the data transfer */
  692.     vlEndTransfer(vlSvr, vlPath);
  693.      
  694.     /* Destroy the path, free it's memory */
  695.     vlDestroyPath(vlSvr, vlPath);
  696.  
  697.     /* Disonnect from the daemon */
  698.     vlCloseVideo(vlSvr);
  699.  
  700.     simplev2v(); /* make sure leave in 'nice' state */
  701.     exit(0);
  702. }
  703.